package gui;

import gnu.cajo.utils.extra.TransparentItemProxy;
import simulation.Connection;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

import simulation.Config;
import lookandfeel.colorScheme;
import lookandfeel.customButton;

import combat.protocol.data.ChatEntry;
import combat.protocol.interfaces.ChatInt;

public class Chat 
{
	private customButton btn_ChatSendMessage = new customButton("Send");
	private JPanel pnl_Chat = new JPanel();
	private JPanel pnl_ImgMessageSend = new JPanel();
	private JScrollPane pnl_ChatLog;
    private JTextField txt_ChatMessageField = new JTextField();
    private JLabel lbl_MessageImg = new JLabel();
    private JTable table = new JTable();
    private DefaultTableModel model = new DefaultTableModel();
    SimpleDateFormat time = new SimpleDateFormat("hh:mm:ss");
    
    public static ChatInt chat;
    
	//Create the arraylist for allmessages
	private ArrayList<ChatEntry> allMessages;
    
    private int width = Toolkit.getDefaultToolkit().getScreenSize().width - 400;
	
	public JPanel getChat()
	{
		return pnl_Chat;
	}
	
	public Chat()
	{
		//Connect to chatserver
		try 
        {
            chat = (ChatInt) TransparentItemProxy.getItem(
            		"//" + Config.cajoHost + ":" + Config.cajoPort + "/Chat", new Class[] { ChatInt.class });
            
            System.out.println("Connection to chat is established.");
        }
        catch (Exception e) 
        {
        	System.out.println("ERROR: Could not connect to Chat server.");
        }
        
        //Spectators cannot send messages, disable Message Field & Send Button
        if(Connection.getMyTeam().getTeamName().equals("Spectator")){
        	txt_ChatMessageField.setEnabled(false);
        	btn_ChatSendMessage.setEnabled(false);
        }
        
        //Generate the chat table
		generateTable();
		
	}
	
	private void generateTable(){    
		allMessages = chat.getChats();
				
		// Create the table and disallow editing mode
        table = new JTable(model){
			private static final long serialVersionUID = 1L;

			public boolean isCellEditable(int rowIndex, int colIndex) {
        		  return false; //Disallow the editing of any cell
        	}
        };

        //Disable row selection
        table.setEnabled(false);

        Dimension screenRes = Toolkit.getDefaultToolkit().getScreenSize();
        int tWidth = (int) (screenRes.getWidth() - 421);
        table.setSize(tWidth, 115);
        
        //Fill rest space
        table.setFillsViewportHeight(true);
        
        // Define headers in array
		String[] headers = { "Time", "Sender", "Team", "Message" };
		
		//Clear column headers
		if(model.getColumnCount() == 0){
			
			// Add headers to model
			for (int i = 0; i < headers.length; ++i){
				model.addColumn(headers[i]);
			}
			
			//Define column widths
			TableColumn col = null;
			int prefSize = 0;
			for(int i = 0; i < headers.length; i++){
				col = table.getColumnModel().getColumn(i);
				switch(i){
				case 0:
					prefSize = 100;
					break;
				case 1:
					prefSize = 150;
					break;
				case 2:
					prefSize = 100;
					break;
				case 3:
					prefSize = table.getWidth() - 350;
					break;
				default:
					prefSize = 100;
				};
				col.setPreferredWidth(prefSize);
				col.setResizable(false);
			}
		}
		
		//Get table header renderer
		final javax.swing.table.DefaultTableCellRenderer headerRenderer = 
			( ( javax.swing.table.DefaultTableCellRenderer )table.
			getTableHeader().getDefaultRenderer() );
		
		//Align headertext left
		headerRenderer.setHorizontalAlignment(SwingConstants.LEFT);
		
		if(chat != null)
		{			
			addRowsToTable(allMessages);
		}
		else
		{
			model.addRow(new Object[]{
						time.format(new Date()), 
						"SYSTEM", 
						"-", 
						"Connection to chat server could not be established..."}); 
		}
	    this.pnl_ChatLog = new JScrollPane(table);
	    
	    // Set chat log size
		this.pnl_ChatLog.setPreferredSize(new Dimension(width, 125));
		this.pnl_ChatLog.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		lbl_MessageImg.setText("Message:");
		
		colorScheme laf = colorScheme.getColorScheme();
		// Set chat message field
		this.txt_ChatMessageField.setText("Message...");
		this.txt_ChatMessageField.setBorder(BorderFactory.createLineBorder(laf.getBoxBackground(),1));
	    this.txt_ChatMessageField.setPreferredSize(new Dimension((width - 150), 25));
	    
	    //Add focuslistener to set sample text
		this.txt_ChatMessageField.addFocusListener(new FocusListener() {
			String sampleText = "Message...";
			@Override
			public void focusLost(FocusEvent arg0) {
				String currentValue = txt_ChatMessageField.getText();
				currentValue = currentValue.replaceAll(" ", "");
				if(currentValue.equalsIgnoreCase("")){
					txt_ChatMessageField.setText(sampleText);
				}
			}

			@Override
			public void focusGained(FocusEvent arg0) {
				if(txt_ChatMessageField.getText().equalsIgnoreCase(sampleText)){
					txt_ChatMessageField.setText("");
				}
				
			}
		});
		this.txt_ChatMessageField.addKeyListener(new KeyListener() {		
			public void keyTyped(KeyEvent e) {}
			public void keyReleased(KeyEvent e) {}

			public void keyPressed(KeyEvent e) {
				int key = e.getKeyCode();
				//If enter is pressed. Manually do a send click
				if(key == KeyEvent.VK_ENTER){
					btn_ChatSendMessage.doClick();
				}	
			}
		});
	   
	    // Add message image, message field, send chat image to one panel
	    this.pnl_ImgMessageSend.add(lbl_MessageImg);
	    this.pnl_ImgMessageSend.add(txt_ChatMessageField);
	    this.pnl_ImgMessageSend.add(btn_ChatSendMessage);
	    
	    // Add & layout the panels into one new panel
	    this.pnl_Chat.setLayout(new BorderLayout());
	    this.pnl_Chat.add(pnl_ChatLog, BorderLayout.NORTH);
	    this.pnl_Chat.add(pnl_ImgMessageSend, BorderLayout.SOUTH);
	    
        // Add selectionlistener to handle clicks on Send button.
        btn_ChatSendMessage.addActionListener(new btnSendOnClick());
	}
	// Send Button action
	class btnSendOnClick implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(txt_ChatMessageField != null && !txt_ChatMessageField.getText().contains("Message..."))
			{
				//Create new chatEntry
				ChatEntry tmpNewEntry = new ChatEntry(
						chat.getNewMessageID(),					//Get new message ID
						Connection.getMe().getUserName(),		//Get username
						Connection.getMyTeam().getTeamName(),	//Get MyTeam
						txt_ChatMessageField.getText()			//Get message body
				);
				chat.sendChat(tmpNewEntry);
				txt_ChatMessageField.setText("");
				
				//Update the table view
				updateChatMessages();
			}
		}
		
	}
	
	private void addRowsToTable(ArrayList<ChatEntry> _messages){
		//Reverse array for new messages at top
		ArrayList<ChatEntry> reverseMessages = new ArrayList<ChatEntry>(_messages);

		for(ChatEntry message : reverseMessages) {
			String target = (String) message.getTarget();
			String team = Connection.getMyTeam().getTeamName();

			//Get team and system chats. Spectator can see all
			if(target.equals(team) || team.equals("Spectator") || team.equals("SYSTEM"))
			{
				model.insertRow(0, new Object[]{
						time.format(message.getTimestamp()), 	//get timestamp
						message.getUserName(), 					// get username
						message.getTarget(),					// get users team
						message.getMessage() 					// get message body
				});
			}
		}
	}

	public void updateChatMessages(){
		ArrayList<ChatEntry> newMessages = new ArrayList<ChatEntry>();
		// Check what the local(!) last known message ID is
		int lastKnownMessageID = 0;
		if(!allMessages.isEmpty()){
			lastKnownMessageID = allMessages.get(allMessages.size() - 1).getMessageID();
		}
		else{
			//Set to -1 to get all messages
			lastKnownMessageID = -1;
		}
		//Get new messages from server
		newMessages = chat.getNewChats(lastKnownMessageID);
		//Add the new messages to the allmessages array list
		if(newMessages.size() >= 0){
			allMessages.addAll(newMessages);
			addRowsToTable(newMessages);
		}
	}
	/****************************/
}
